package info.tsukaworld.actor.mob.pathfinding;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


public final class Path
    implements Comparable<Path>
{
    final Path parent;
    private final Tile tile;
    private final int cost;
    private final int distance;
    private final int heuristic;

    public Path(final Path p,
                final Tile t,
                final int  h)
    {
        parent    = p;
        heuristic = h;

        if(parent == null)
        {
            distance = 0;
            cost     = heuristic;
        }
        else
        {
            distance = parent.distance + 1;
            cost     = distance + heuristic;
        }
        
        tile = t;
    }

    public int getCost()
    {
        return (cost);
    }

    public Tile getTile()
    {
        return (tile);
    }

    public List<Tile> getTiles()
    {
        final List<Tile> tiles;
        Path             temp;

        tiles = new ArrayList<Tile>();

        tiles.add(tile);
        temp = parent;

        while(temp != null)
        {
            tiles.add(temp.tile);
            temp = temp.parent;
        }
        
        Collections.reverse(tiles);

        return (tiles);
    }

    @Override
    public int hashCode()
    {
        final int retVal;

        if(parent == null)
        {
            retVal = cost * tile.hashCode();
        }
        else
        {
            retVal = (cost * (parent.hashCode() + tile.hashCode()));
        }

        return (retVal);
    }

    @Override
    public boolean equals(final Object o)
    {
        final boolean retVal;

        if(this == o)
        {
            return true;
        }

        if(o instanceof Path)
        {
            final Path other;

            other = (Path)o;

            if(cost == other.cost)
            {
                if(tile.equals(other.tile))
                {
                    retVal = parent.equals(other.parent);
                }
                else
                {
                    retVal = false;
                }
            }
            else
            {
                retVal = false;
            }
        }
        else
        {
            retVal = false;
        }

        return (retVal);
    }

    @Override
    public String toString()
    {
        final StringBuilder builder;

        builder = new StringBuilder();
        toString(builder);

        return (builder.toString());
    }

    private void toString(final StringBuilder builder)
    {
        if(parent != null)
        {
            parent.toString(builder);
            builder.append(", ");
        }

        builder.append("distance: " + distance);
        builder.append(" heuristic: " + heuristic);
        builder.append(" cost: " + cost);
        builder.append(" -> ");
        builder.append(tile);
        builder.append("\r\n");
    }

    public int compareTo(final Path other)
    {
        if(cost > other.cost)
        {
            return (1);
        }
        else if(cost < other.cost)
        {
            return (-1);
        }

        return (0);
    }
}